<template>
  <div class="rightMenu">
    <el-row style="height: 100%">
      <el-col :span="6" style="height: 100%">
        <pageCard :title-name="'菜单管理'" :type="'pageTitle'" class="left">
          <el-input v-model="filterText" placeholder="输入关键字进行过滤" style="padding-bottom: 10px" />
          <el-scrollbar style="height: calc(100% - 42px)">
            <el-tree
              ref="tree"
              :data="rightTree"
              default-expand-all
              node-key="id"
              highlight-current
              :expand-on-click-node="false"
              :filter-node-method="filterNode"
              :props="defaultProps"
              @node-click="nodeClick"
            >
              <div slot-scope="{ node, data }" class="treeRow">
                <i v-if="data.children.length > 0" class="el-icon-folder-opened" />
                <i v-else class="el-icon-document" />
                <span class="treeLabel">{{ node.label }}</span>
              </div>
            </el-tree>
          </el-scrollbar>
        </pageCard>
      </el-col>
      <el-col :span="18" style="height: 100%">
        <pageCard :title-name="'菜单列表'" class="right" style="height: 100%" :type="'pageTitle'">
          <div class="searchDiv">
            <div class="topText">菜单名称：</div>
            <el-input
              v-model="search.rightName"
              placeholder="请输入"
              class="searchInput"
              @keyup.enter.native="searchClick"
            />
            <div class="topText">状态：</div>
            <el-select v-model="search.disable" class="searchSelect" clearable>
              <el-option label="正常" value="0"></el-option>
              <el-option label="停用" value="1"></el-option>
            </el-select>
            <el-button type="primary" class="topBtn" @click="searchClick">搜索</el-button>
            <el-button type="primary" plain class="topBtn" @click="clearClick">重置</el-button>
            <div class="rightBtn">
              <el-button type="primary" class="topBtn" @click="handleClick('add')">新增</el-button>
            </div>
          </div>
          <div class="xTable">
            <vxe-table
              ref="xTable"
              height="auto"
              show-overflow
              keep-source
              row-id="rightId"
              :loading="loading"
              :tree-config="{ transform: false, rowField: 'rightId', parentField: 'parentId' }"
              :data="tableData"
            >
              <vxe-column field="rightName" title="菜单名称" tree-node></vxe-column>
              <vxe-column field="component" title="组件路径"></vxe-column>
              <vxe-column field="orderId" title="排序" width="80"></vxe-column>
              <vxe-column field="rightType" title="类型" width="100">
                <template #default="{ row }">
                  <span v-if="row.rightType === 1" class="tag blueColor">菜单</span>
                  <span v-else class="tag purpleColor">权限</span>
                </template>
              </vxe-column>
              <vxe-column field="hidden" title="可见" width="100">
                <template #default="{ row }">
                  <span v-if="row.hidden === 0" class="tag cyanColor">显示</span>
                  <span v-else class="tag silveryColor">隐藏</span>
                </template>
              </vxe-column>
              <vxe-column field="rightCode" title="权限标识" width="150"></vxe-column>
              <vxe-column field="disable" title="状态" width="100">
                <template #default="{ row }">
                  <span v-if="row.disable === 0" class="tag greenColor">正常</span>
                  <span v-else class="tag redColor">停用</span>
                </template>
              </vxe-column>
              <vxe-column title="操作" width="280">
                <template #default="{ row }">
                  <el-link :underline="false" type="primary" @click="handleClick('edit', row)">修改</el-link>
                  <el-divider direction="vertical"></el-divider>
                  <el-popconfirm
                    :title="'是否确认' + (row.disable === 1 ? '启用' : '停用') + '菜单?'"
                    @confirm="handleClick('enable', row)"
                  >
                    <el-link slot="reference" :underline="false" type="primary">
                      {{ row.disable === 1 ? '启用' : '停用' }}
                    </el-link>
                  </el-popconfirm>
                  <el-divider direction="vertical"></el-divider>
                  <el-popconfirm title="确定删除吗？" @confirm="handleClick('del', row)">
                    <el-link slot="reference" :underline="false" type="primary">删除</el-link>
                  </el-popconfirm>
                  <el-divider direction="vertical"></el-divider>
                  <el-link
                    :disabled="row.rightType === 2"
                    :underline="false"
                    type="primary"
                    @click="handleClick('addChild', row)"
                  >
                    新增子节点
                  </el-link>
                </template>
              </vxe-column>
            </vxe-table>
          </div>
        </pageCard>
      </el-col>
    </el-row>
    <setRight
      v-if="pageType !== 'index'"
      ref="setRight"
      :right-code-list="rightCodeList"
      :component-tree-data="componentTreeData"
      @submitForm="submitForm"
      @closeForm="pageType = 'index'"
    />
  </div>
</template>

<script>
import pageCard from '@/components/page/pageCard'
import setRight from './components/setRight'
import {
  loadRightCodeOptions,
  addRight,
  updateRight,
  getRightTree,
  loadRightGird,
  disableRight,
  deleteRight
} from '@/api/system-management'
import defaultSettings from '@/settings'
import { generateUUID, postMessage, receivedMessage } from '@/utils/index'
import { resetRouterMenu } from '@/router'
export default {
  name: 'Right',
  components: {
    pageCard,
    setRight
  },
  data() {
    return {
      // 树data
      filterText: '',
      rightTree: [],
      defaultProps: {
        children: 'children',
        label: 'label'
      },
      currentNode: {},
      rightCodeList: [],
      menuTree: [],

      // 表格
      loading: false,
      tableData: [],
      treeExpandRecords: [],
      search: {
        rightName: '',
        disable: undefined
      },
      pageType: 'index',
      flag: false,

      componentTreeData: [],
      loadRightCodeOptionsRequestId: generateUUID(),
      getRightTreeRequestId: generateUUID(),
      loadRightGirdRequestId: generateUUID()
    }
  },
  watch: {
    filterText(val) {
      this.$refs.tree.filter(val)
    }
  },
  mounted() {
    this.componentTreeData = this.delEmptyChildren(this.getFileTree())
    this.getRightCodeData()
    this.getRightTree()
    this.getTableData()

    receivedMessage(this.dataHandle)
  },
  methods: {
    dataHandle(result) {
      let self = this
      let e = defaultSettings.isWPF ? result : { data: JSON.parse(result) }
      if (e.data.webInfo.requestId === self.loadRightCodeOptionsRequestId) {
        let res = e.data.response
        self.rightCodeList = res.data.options
      } else if (e.data.webInfo.requestId === self.getRightTreeRequestId) {
        let res = e.data.response
        self.rightTree = res.data
        if (self.currentNode.id) {
          self.$nextTick(() => {
            self.$refs.tree.setCurrentKey(self.currentNode.id)
          })
        }
      } else if (e.data.webInfo.requestId === self.loadRightGirdRequestId) {
        self.getRightData(e.data.response)
      }
    },
    getRightCodeData() {
      if (defaultSettings.isWPF || defaultSettings.isCEF) {
        this.loadRightCodeOptionsRequestId = generateUUID()
        let message = {
          RequestUrl: process.env.VUE_APP_URL + '/right/loadRightCodeOptions',
          RequestMethod: 'POST',
          Headers: {
            contentType: 'application/json'
          },
          QueryParameter: {},
          RequestBody: {},
          WebInfo: {
            requestId: this.loadRightCodeOptionsRequestId
          }
        }
        postMessage(message)
      } else {
        loadRightCodeOptions().then((res) => {
          this.rightCodeList = res.data.options
        })
      }
    },
    getFileTree() {
      const baseData = require
        .context(
          '@/views',
          true,
          /^(?!.*(?:components|redirect|nested|navigation-page|big-screen\/screen|login\/index|404.vue|refresh.vue$)).*\.vue$/
        )
        .keys()
        .map((item) => {
          return item.substring(2, item.lastIndexOf('.vue'))
        })
      const treeDTO = [{ label: 'Layout', value: 'Layout', children: [] }]
      baseData.forEach((item) => {
        const nodeArray = item.split('/')
        let children = treeDTO
        // 循环构建子节点
        for (let i of nodeArray) {
          const node = {
            label: i,
            value: i
          }
          if (children.length === 0) {
            children.push(node)
          }
          let isExist = false
          for (const j in children) {
            if (children[j].label === node.label) {
              if (!children[j].children) {
                children[j].children = []
              }
              children = children[j].children
              isExist = true
              break
            }
          }
          if (!isExist) {
            children.push(node)
            if (!children[children.length - 1].children) {
              children[children.length - 1].children = []
            }
            children = children[children.length - 1].children
          }
        }
      })
      return treeDTO
    },
    delEmptyChildren(data) {
      data.forEach((item) => {
        if (item.children.length === 0) {
          delete item.children
        } else {
          this.delEmptyChildren(item.children)
        }
      })
      return data
    },
    // 获取菜单树
    getRightTree() {
      if (defaultSettings.isWPF || defaultSettings.isCEF) {
        this.getRightTreeRequestId = generateUUID()
        let message = {
          RequestUrl: process.env.VUE_APP_URL + '/right/loadTree',
          RequestMethod: 'POST',
          Headers: {
            contentType: 'application/json'
          },
          QueryParameter: {},
          RequestBody: {},
          WebInfo: {
            requestId: this.getRightTreeRequestId
          }
        }
        postMessage(message)
      } else {
        getRightTree().then((res) => {
          this.rightTree = res.data
          if (this.currentNode.id) {
            this.$nextTick(() => {
              this.$refs.tree.setCurrentKey(this.currentNode.id)
            })
          }
        })
      }
    },
    searchClick() {
      this.getTableData()
    },
    clearClick() {
      this.currentNode = {}
      this.$refs.tree.setCurrentKey(null)
      this.search = {}
      this.getTableData()
    },
    getTableData(flag = false) {
      this.loading = true
      this.flag = flag
      let params = { ...this.search, parentRightId: this.currentNode.id }
      if (defaultSettings.isWPF || defaultSettings.isCEF) {
        this.loadRightGirdRequestId = generateUUID()
        let message = {
          RequestUrl: process.env.VUE_APP_URL + '/right/loadRightGird',
          RequestMethod: 'POST',
          Headers: {
            contentType: 'application/json'
          },
          QueryParameter: {},
          RequestBody: params,
          WebInfo: {
            requestId: this.loadRightGirdRequestId
          }
        }
        postMessage(message)
      } else {
        loadRightGird(params).then((res) => {
          this.getRightData(res)
        })
      }
    },
    getRightData(res) {
      this.loading = false
      this.tableData = res.data
      if (this.flag) {
        let rightIds = this.treeExpandRecords.map((item) => item.rightId)
        const setTreeExpand = (data) => {
          data.forEach((item) => {
            if (rightIds.includes(item.rightId)) {
              this.$refs.xTable.setTreeExpand(item, true)
            }
            if (item.children && item.children.length > 0) {
              setTreeExpand(item.children)
            }
          })
        }
        setTreeExpand(this.tableData)
      } else {
        if (this.currentNode.id) {
          // this.$nextTick(() => {
          this.tableData.every((item) => {
            if (item.rightId === this.currentNode.id) {
              this.$refs.xTable.setTreeExpand(item, true)
              return false
            }
            return true
          })
          // })
        }
      }
    },
    getPath(path, name) {
      if (name === 'path') {
        if (path) {
          if (path.indexOf('/') === 0) {
            return path.substr(1)
          } else if (path.indexOf('http://') === 0) {
            return path.substr(7)
          } else if (path.indexOf('https://') === 0) {
            return path.substr(8)
          } else {
            return path
          }
        } else {
          return ''
        }
      } else {
        if (path) {
          if (path.indexOf('/') === 0) {
            return '/'
          } else if (path.indexOf('http://') === 0) {
            return 'http://'
          } else if (path.indexOf('https://') === 0) {
            return 'https://'
          } else {
            return ''
          }
        } else {
          return ''
        }
      }
    },
    handleClick(type, row) {
      this.pageType = type

      if (['add', 'edit', 'addChild'].includes(type)) {
        this.$nextTick(() => {
          this.$refs.setRight.is(
            type,
            type === 'edit'
              ? {
                  ...row,
                  path: this.getPath(row.path, 'path'),
                  prependPath: this.getPath(row.path, 'prependPath'),
                  component: row.component ? row.component.split('/') : []
                }
              : {
                  rightType: row?.children && row.children?.[0]?.rightType === 2 ? 2 : 1,
                  parentId: row?.rightId ? row.rightId : 0,
                  prependPath: '',
                  hidden: 0,
                  disable: 0,
                  noCache: 1,
                  orderId: 1,
                  alwaysShow: 0,
                  affix: 0,
                  component: []
                }
          )
        })
      } else if (type === 'enable') {
        // 停用 启用 菜单
        disableRight({ rightId: row.rightId, disable: Number(!row.disable) }).then((res) => {
          if (res.success) {
            resetRouterMenu()
            this.$message.success(row.disable === 1 ? '启用成功' : '停用成功')
            this.setRightDisable([row], Number(!row.disable))
          } else {
            this.$message.error(res.message)
          }
        })
      } else if (type === 'del') {
        // 删除菜单
        deleteRight({ rightId: row.rightId }).then((res) => {
          if (res.success) {
           resetRouterMenu()
            this.$message.success('删除成功')
            if (row.parentId === 0) {
              let index = this.tableData.findIndex((item) => item.rightId === row.rightId)
              this.tableData.splice(index, 1)
            } else {
              let parentNode = this.findNode(this.tableData, 'rightId', row.parentId, [])
              let index = parentNode.children.findIndex((item) => item.rightId === row.rightId)
              parentNode.children.splice(index, 1)
            }
            this.$refs.tree.remove(row.rightId)
          } else {
            this.$message.error(res.message)
          }
        })
      }
    },
    setRightDisable(data, disable) {
      data.forEach((row) => {
        row.disable = disable
        if (row.children && row.children.length > 0) {
          this.setRightDisable(row.children, disable)
        }
      })
    },
    findNode(data, prop, val, result) {
      data.forEach((item) => {
        if (item[prop] === val) {
          result.push(item)
          return false
        }
        if (item.children && item.children.length > 0) {
          this.findNode(item.children, prop, val, result)
        }
        return true
      })
      return result[0]
    },
    // 提交表单函数
    submitForm(data) {
      this.treeExpandRecords = this.$refs.xTable.getTreeExpandRecords()

      let formData = JSON.parse(JSON.stringify(data))
      if (data.rightType === 2) {
        formData.routerName = ''
        formData.path = ''
        formData.component = ''
        formData.redirect = ''
        formData.icon = ''
        formData.alwaysShow = 0
        formData.noCache = 1
        formData.affix = 0
      } else {
        formData.path = formData.prependPath + formData.path
        formData.component = formData.component.length > 0 ? formData.component.join('/') : ''
      }
      // console.log(formData)
      // return
      if (this.pageType === 'edit') {
        updateRight(formData).then((res) => {
          this.getRightTree()
          this.getTableData(true)
          resetRouterMenu()
          this.$notify({
            message: '修改菜单成功',
            type: 'success'
          })
          this.pageType = 'index'
        })
      } else {
        addRight(formData).then((res) => {
          if (this.$store.state.user.roles.includes('1000')) {
            resetRouterMenu()
          }
          this.getRightTree()
          this.getTableData(true)
          this.$notify({
            message: '新增菜单成功',
            type: 'success'
          })

          this.pageType = 'index'
        })
      }
    },

    // 以下树函数
    // 过滤树函数
    filterNode(value, data) {
      if (!value) return true
      return data.label.indexOf(value) !== -1
    },
    // 点击节点
    async nodeClick(node) {
      this.currentNode = node
      this.getTableData()
    }
  }
}
</script>
<style lang="less" scoped>
@import '@/styles/pageTableTop.scss';

.rightMenu {
  height: 99%;
  .left {
    /deep/.el-scrollbar__view {
      height: 100%;
    }
    .treeRow {
      display: flex;
      align-items: center;
      .treeLabel {
        font-size: 14px;
        padding-left: 5px;
      }
    }
  }
  .right {
    /deep/.el-scrollbar__view {
      height: 100%;
      display: flex;
      flex-direction: column;
    }

    .searchDiv {
      margin-bottom: 10px;
      .rightBtn {
        position: absolute;
        right: -10px;
        top: 8px;
      }
    }
    .xTable {
      flex: 1;
      max-height: calc(100% - 50px);
      /deep/.vxe-table--empty-placeholder {
        top: 50% !important;
      }
      /deep/.vxe-table--render-default .vxe-cell {
        padding-right: 0;
      }
      .tag {
        display: inline-block;
        height: 24px;
        padding: 0 8px;
        line-height: 22px;
        font-size: 12px;
        border-width: 1px;
        border-style: solid;
        border-radius: 4px;
        box-sizing: border-box;
        white-space: nowrap;
      }
      .blueColor {
        background-color: #e6efff;
        border-color: #cce0ff;
        color: #0062ff;
      }
      .purpleColor {
        color: #531dab;
        background: #f9f0ff;
        border-color: #d3adf7;
      }
      .cyanColor {
        color: #08979c;
        background: #e6fffb;
        border-color: #87e8de;
      }
      .silveryColor {
        background-color: #f4f4f5;
        border-color: #e9e9eb;
        color: #909399;
      }
      .greenColor {
        background-color: #f0f9eb;
        border-color: #e1f3d8;
        color: #67c23a;
      }
      .redColor {
        background-color: #fef0f0;
        border-color: #fde2e2;
        color: #f56c6c;
      }
    }
  }
}
</style>
